package com.videoweb.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.videoweb.constant.Constants;
import com.videoweb.entity.*;
import com.videoweb.entity.dto.VideoItemDTO;
import com.videoweb.entity.dto.VideoUploadDTO;
import com.videoweb.mapper.*;
import com.videoweb.service.IVideoService;
import com.videoweb.service.VideoAuditService.PublishService;
import com.videoweb.utils.DurationUtils;
import com.videoweb.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lmr
 * @since 2025-05-17
 */
@Service
//确保整个操作原子性
// 任何步骤失败都会回滚所有操作
//保证数据一致性（不会出现只有部分记录插入的情况）
@Transactional
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements IVideoService {

    @Autowired
    FileMapper fileMapper;
    @Autowired
    VideoMapper videoMapper;

    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    TagMapper tagMapper;
    @Autowired
    VideoTagMapper videoTagMapper;
   @Autowired
    PublishService publishService;



    public void uploadVideo(VideoUploadDTO dto) {
        Long userId = SecurityUtils.getUserId();
        dto.setUserId(userId);
        // 1. 处理分类
        Long categoryId = handleCategory(dto.getCategory());
        // 2. 保存视频文件
        File videoFile = new File();
        videoFile.setFileKey(dto.getVideoFile().getFileKey());
        videoFile.setType("video");
        videoFile.setFormat(dto.getVideoFile().getFormat());
//                                              转化为毫秒保存到数据库中
        videoFile.setDuration(DurationUtils.toMillisecond(dto.getVideoFile().getDuration()));
        videoFile.setSize(dto.getVideoFile().getSize());

//        todo 2025/6/02 改一下从SpringSecurity上下文中获取
        videoFile.setUserId(dto.getUserId());
        fileMapper.insertFile(videoFile);

        // 3. 保存封面文件
        File coverFile = new File();
        coverFile.setFileKey(dto.getCoverFile().getFileKey());
        coverFile.setType("image");
        coverFile.setFormat(dto.getCoverFile().getFormat());
        coverFile.setSize(dto.getCoverFile().getSize());
        coverFile.setUserId(dto.getUserId());
        fileMapper.insertFile(coverFile);

        // 4. 保存视频主记录
        Video video = new Video();
        video.setTitle(dto.getTitle());
        video.setDescription(dto.getDescription());
        video.setVideoFileId(videoFile.getId());
        video.setCoverFileId(coverFile.getId());
        video.setCategoryId(categoryId);
        video.setUserId(dto.getUserId());
//        一样 转化为毫秒
        video.setDuration(videoFile.getDuration());
        videoMapper.insertVideo(video);

        System.out.println(video);

        // 5. 处理标签
        handleTags(dto.getTags(), video.getId());

        // 6. 对视频进行审核
        publishService.auditAsync(video, Constants.CNAME+coverFile.getFileKey(), Constants.CNAME+videoFile.getFileKey());

    }
    private Long handleCategory(String categoryName) {
        Long categoryId = categoryMapper.findIdByName(categoryName);
        if (categoryId != null) return categoryId;
        Category category = new Category();
        category.setName(categoryName);
        category.setDescription(categoryName + "类视频");
        categoryMapper.insertCategory(category);
        return category.getId();
    }
    private void handleTags(List<String> tagNames, Long videoId) {
        if (tagNames == null || tagNames.isEmpty()) return;

        // 插入新标签（忽略重复）
        List<Tag> newTags = tagNames.stream()
                .distinct()
                .map(name -> new Tag(name))
                .collect(Collectors.toList());
        if (!newTags.isEmpty()) {
//            添加新的标签
            tagMapper.batchInsertTags(newTags);
        }
        // 获取标签ID
        List<Long> tagIds = tagMapper.findTagIdsByNames(tagNames);
        System.out.println(tagIds);

        // 创建关联
        List<VideoTag> videoTags = tagIds.stream()
                .map(tagId -> new VideoTag(videoId, tagId))
                .collect(Collectors.toList());

        if (!videoTags.isEmpty()) {
            videoTagMapper.batchInsertVideoTags(videoTags);
        }
    }


    //    查看所有的视频
    @Override
    public List<VideoItemDTO> findVideoItem() {
        List<VideoItemDTO> videoItemDTOS = videoMapper.findVideoItem();
        return videoItemDTOS;
    }

    @Override
    public List<Video> findVideo() {
        PageHelper.startPage(1, 2);
        List<Video> videos = videoMapper.selectList(null);
        return videos;
    }

    @Override
    public List<VideoItemDTO> findVideoItemByPage(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<VideoItemDTO> videoItemDTOS = videoMapper.findVideoItem();

        return videoItemDTOS;
    }


    //    查视频 根据分类ID
    @Override
    public List<VideoItemDTO> findVideoByCategoryId(Long categoryId) {
        return videoMapper.findVideoByCategoryId(categoryId);
    }

    //    查视频 根据标签ID
    @Override
    public List<VideoItemDTO> findVideoByTagID(Long tagId) {
        return videoMapper.findVideoByTagID(tagId);
    }

    //    查视频 根据用户ID   findVideoByTagID   findVideoByUserID
    @Override
    public List<VideoItemDTO> findVideoByUserID(Long userId) {
        return videoMapper.findVideoByUserID(userId);
    }

    @Override
    public VideoItemDTO finVideoByVideoId(Long videoId) {
        return videoMapper.finVideoByVideoId(videoId);
    }


    @Override
    public List<VideoItemDTO> finVideoByFavoritesId(Long favoritesId) {
        return videoMapper.findVideoByFavoritesId(favoritesId);
    }

    @Override
    public int updateStatusByVideoId(Long videoId, Integer status) {
        LambdaUpdateWrapper<Video> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Video::getId, videoId)
                .set(Video::getStatus, status);
        int row = videoMapper.update(null, lambdaUpdateWrapper);


        return row;
    }


}
